package com.xuecheng.learning.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xuecheng.learning.feignclient.ContentServiceClient;
import com.xuecheng.learning.mapper.XcChooseCourseMapper;
import com.xuecheng.learning.mapper.XcCourseTablesMapper;
import com.xuecheng.learning.model.dto.MyCourseTableParams;
import com.xuecheng.learning.model.dto.XcChooseCourseDto;
import com.xuecheng.learning.model.dto.XcCourseTablesDto;
import com.xuecheng.learning.model.po.XcChooseCourse;
import com.xuecheng.learning.model.po.XcCourseTables;
import com.xuecheng.learning.service.MyCourseTablesService;
import com.zmt.content.po.CoursePublish;
import com.zmt.xuechengplusbase.exception.xuechengplusException;
import com.zmt.xuechengplusbase.model.PageParams;
import com.zmt.xuechengplusbase.model.PageResult;
import com.zmt.xuechengplusbase.utils.StringUtil;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDateTime;
import java.util.List;

@Slf4j
@Service
public class MyCourseTablesServiceImpl implements MyCourseTablesService {

    @Autowired
    private XcChooseCourseMapper xcChooseCourseMapper;

    @Autowired
    private XcCourseTablesMapper xcCourseTablesMapper;

    @Autowired
    private ContentServiceClient contentServiceClient;

    @Override
    public XcChooseCourseDto addChooseCourse(String userId, Long courseId) {
        //先进行一个判断选课表上是否已经存在
        //远程调用去查询课程收费规则
        CoursePublish coursepublish = contentServiceClient.getCoursepublish(courseId);
        if (coursepublish == null) {
            xuechengplusException.cast("课程不存在");
        }
        String charge = coursepublish.getCharge();
        XcChooseCourse xcChooseCourse = new XcChooseCourse();
        if ("201000".equals(charge)) {
            //说明免费，直接插入两张表
            xcChooseCourse = addFreeCourse(userId, coursepublish);
            addCourseTable(xcChooseCourse);
        } else {
            //说明收费，只向选课表中插入数据
            xcChooseCourse = addChargeCourse(userId, coursepublish);
        }
        XcCourseTablesDto xcCourseTablesDto = getLearningStatus(userId, courseId);

        //构造返回参数
        XcChooseCourseDto xcChooseCourseDto = new XcChooseCourseDto();
        BeanUtils.copyProperties(xcChooseCourse, xcChooseCourseDto);
        xcChooseCourseDto.setLearnStatus(xcCourseTablesDto.getLearnStatus());
        return xcChooseCourseDto;
    }

    /**
     * 获取课程的学习资格
     * [{"code":"702001","desc":"正常学习"},{"code":"702002","desc":"没有选课或选课后没有支付"},{"code":"702003","desc":"已过期需要申请续期或重新支付"}]
     *
     * @param userId
     * @param courseId
     * @return
     */
    @Override
    public XcCourseTablesDto getLearningStatus(String userId, Long courseId) {
        LambdaQueryWrapper<XcCourseTables> wrapper = new LambdaQueryWrapper<XcCourseTables>().eq(XcCourseTables::getCourseId, courseId).eq(XcCourseTables::getUserId, userId);
        XcCourseTables xcCourseTables = xcCourseTablesMapper.selectOne(wrapper);
        XcCourseTablesDto xcCourseTablesDto = new XcCourseTablesDto();
        if (xcCourseTables == null) {
            xcCourseTablesDto.setLearnStatus("702002");
            return xcCourseTablesDto;
        }
        BeanUtils.copyProperties(xcCourseTables, xcCourseTablesDto);
        //判断是否过期
        boolean before = xcCourseTables.getValidtimeEnd().isBefore(LocalDateTime.now());
        if (before) {
            xcCourseTablesDto.setLearnStatus("702003");
            return xcCourseTablesDto;
        } else {
            xcCourseTablesDto.setLearnStatus("702001");
            return xcCourseTablesDto;
        }
    }

    /**
     * 订单服务发送消息给学习中心，保存选课记录
     *
     * @param chooseCourseId
     * @return
     */
    @Override
    @Transactional
    public boolean saveChooseCourseSuccess(String chooseCourseId) {
        //修改选课表的信息为选课成功。
        XcChooseCourse xcChooseCourse = xcChooseCourseMapper.selectById(chooseCourseId);
        if (xcChooseCourse == null) {
            log.error("收到了支付成功通知却没有选课消息,选课id：{}", chooseCourseId);
            return false;
        }

        String status = xcChooseCourse.getStatus();
        if (status.equals("701001")) {
            log.debug("已经选课成功，为什么还有通知?选课id：{}", chooseCourseId);//可能是主动通知后又点击了支付成功按钮进行了二次确认导致发送了两条消息
            addCourseTable(xcChooseCourse);//可是为什么还要进行添加呢？第一次消息就已经进行了添加
            return true;
        }
        if ("701002".equals(status)) {
            //如果还是未支付的状态，说明是第一次接收到消息
            xcChooseCourse.setStatus("701001");
            //更新选课表
            int i = xcChooseCourseMapper.updateById(xcChooseCourse);
            if (i < 0) {
                log.error("更新选课表失败，选课id为{}", chooseCourseId);
            } else {
                log.debug("更新选课表成功,选课id为{}", chooseCourseId);
            }
            //更新课程表
            addCourseTable(xcChooseCourse);
            return true;
        }
        return false;
    }

    /**
     * @param userId
     * @param params
     * @return
     */
    @Override
    public PageResult<XcCourseTables> getMyCourseTable(String userId, MyCourseTableParams params) {
        //构造分页参数
        Long pageNo = params.getPage();
        Long pageSize = params.getSize();
        Page<XcCourseTables> pageInfo = new Page<>(pageNo,pageSize);
        //从前端拿到的参数按条件进行查寻
        LambdaQueryWrapper<XcCourseTables> wrapper = new LambdaQueryWrapper<>();
        wrapper.eq(XcCourseTables::getUserId, userId)
                .eq(StringUtil.isNotEmpty(params.getCourseType()), XcCourseTables::getCourseType, params.getCourseType());
        Page<XcCourseTables> xcCourseTablesPage = xcCourseTablesMapper.selectPage(pageInfo, wrapper);
        List<XcCourseTables> records = xcCourseTablesPage.getRecords();
        long total = xcCourseTablesPage.getTotal();
        PageParams pageParams = new PageParams();
        pageParams.setPageNo(pageNo);
        pageParams.setPageSize(pageSize);
        PageResult<XcCourseTables> pageResult = new PageResult<XcCourseTables>(records,total,pageParams);
        return pageResult;
    }


    public XcChooseCourse addFreeCourse(String userId, CoursePublish coursepublish) {
        Long courseId = coursepublish.getId();
        LambdaQueryWrapper<XcChooseCourse> wrapper = new LambdaQueryWrapper<XcChooseCourse>()
                .eq(XcChooseCourse::getCourseId, courseId)
                .eq(XcChooseCourse::getUserId, userId)
                .eq(XcChooseCourse::getOrderType, "700001")//查询有没有这个id的免费课程
                .eq(XcChooseCourse::getStatus, "701001");//都免费了为啥还要查询支付状态……
        //因为没有约束所以可能存在一个人一个课程插入多条数据的情况
        List<XcChooseCourse> xcChooseCourses = xcChooseCourseMapper.selectList(wrapper);
        if (xcChooseCourses.size() > 0) {
            //返回一条数据就行
            return xcChooseCourses.get(0);
        }
        XcChooseCourse xcChooseCourse = new XcChooseCourse();
        xcChooseCourse.setCourseId(coursepublish.getId());
        xcChooseCourse.setCourseName(coursepublish.getName());
        xcChooseCourse.setCoursePrice(0f);//免费课程价格为0
        xcChooseCourse.setUserId(userId);
        xcChooseCourse.setCompanyId(coursepublish.getCompanyId());
        xcChooseCourse.setOrderType("700001");//免费课程
        xcChooseCourse.setCreateDate(LocalDateTime.now());
        xcChooseCourse.setStatus("701001");//选课成功
        xcChooseCourse.setValidDays(365);//免费课程默认365
        xcChooseCourse.setValidtimeStart(LocalDateTime.now());
        xcChooseCourse.setValidtimeEnd(LocalDateTime.now().plusDays(365));

        int insert = xcChooseCourseMapper.insert(xcChooseCourse);
        if (insert < 0) {
            xuechengplusException.cast("添加课程失败");
        }
        return xcChooseCourse;

    }

    /**
     * 向课程表中添加数据
     *
     * @param xcChooseCourse
     * @return
     */
    public XcCourseTables addCourseTable(XcChooseCourse xcChooseCourse) {
        Long courseId = xcChooseCourse.getCourseId();
        String userId = xcChooseCourse.getUserId();
        //查询课程表中是否存在
        XcCourseTables xcCourseTables = xcCourseTablesMapper.selectOne(new LambdaQueryWrapper<XcCourseTables>().eq(XcCourseTables::getUserId, userId).eq(XcCourseTables::getCourseId, courseId));
        if (xcCourseTables != null) {
            return xcCourseTables;
        }
        xcCourseTables = new XcCourseTables();
        BeanUtils.copyProperties(xcChooseCourse, xcCourseTables);
        xcCourseTables.setChooseCourseId(xcChooseCourse.getId());
        xcCourseTables.setCourseType(xcChooseCourse.getOrderType());
        int insert = xcCourseTablesMapper.insert(xcCourseTables);
        if (insert < 0) {
            xuechengplusException.cast("添加课程表失败");
        }
        return xcCourseTables;
    }

    public XcChooseCourse addChargeCourse(String userId, CoursePublish coursepublish) {
        Long courseId = coursepublish.getId();
        LambdaQueryWrapper<XcChooseCourse> wrapper = new LambdaQueryWrapper<XcChooseCourse>()
                .eq(XcChooseCourse::getCourseId, courseId)
                .eq(XcChooseCourse::getUserId, userId)
                .eq(XcChooseCourse::getOrderType, "700002")
                //解决方案，将eq修改为in使其和两个字段进行比较，防止反复插入选课信息
                .in(XcChooseCourse::getStatus, "701001", "701002");//这里判断的是选课表中是否存在还未支付的，
        //TODO 如果已经进行了支付，那么去查询时查不到，导致再向其中插入一条数据，在订单服务中，查询到还有未支付的记录后就再次生成二维码导致重复支付，得改

        //因为没有约束所以可能存在一个人一个课程插入多条数据的情况
        List<XcChooseCourse> xcChooseCourses = xcChooseCourseMapper.selectList(wrapper);
        if (xcChooseCourses.size() > 0) {
            //返回一条数据就行
            return xcChooseCourses.get(0);
        }
        XcChooseCourse xcChooseCourse = new XcChooseCourse();
        xcChooseCourse.setCourseId(coursepublish.getId());
        xcChooseCourse.setCourseName(coursepublish.getName());
        xcChooseCourse.setCoursePrice(coursepublish.getPrice());//免费课程价格为0
        xcChooseCourse.setUserId(userId);
        xcChooseCourse.setCompanyId(coursepublish.getCompanyId());
        xcChooseCourse.setOrderType("700002");//收费课程
        xcChooseCourse.setCreateDate(LocalDateTime.now());
        xcChooseCourse.setStatus("701002");//待支付
        xcChooseCourse.setValidDays(365);//免费课程默认365
        xcChooseCourse.setValidtimeStart(LocalDateTime.now());
        xcChooseCourse.setValidtimeEnd(LocalDateTime.now().plusDays(365));

        int insert = xcChooseCourseMapper.insert(xcChooseCourse);
        if (insert < 0) {
            xuechengplusException.cast("添加课程失败");
        }
        return xcChooseCourse;

    }
}
